import core from '@/core/'

// 用户地区信息里面的公共内容
const common = {
	// 暂时只要以下数据
	country: '',
	country_code: '',
	province: '',
	province_code: '',
	city: '',
	city_code: '',
	county: '',
	county_code: '',
	town: '',
	town_code: '',
	formatted_address: '',
	longitude: null,
	latitude: null,
	
	/**
	 * 当前地区信息获取状态
	 * 0：未获取
	 * 1：已获取
	 * 2：获取中。主要针对于用户位置授权，很可能需要处理很长一段时间
	 */
	status: 0,
	
	// 地址信息特有
	name: '',
	phone: '',
}

// 用户的基础信息，一般是用户数据库内容，额外包含一个特殊字段data：登录成功后结果中的data，一般会记录其它信息，比如站点登录会返回用户的权限信息
const info = {}
// 用户的认证信息
const certify = {}
// 用户的第三方授权信息
const openid = {}
// 用户的地区信息
const position = {
	isFetch: false,
	// 用户的第三方平台授权的位置。一般不具备参考性
	third: {},
	// 用户的授权位置
	authorize: {},
	// 用户选择的位置
	selection: {},
	// 用户的家乡位置
	hometown: {},
	// 用户当前电话号码的位置
	phone: {},
	// 用户关注的位置。可以包含多个位置
	attention: [],
	// 用户的地址信息。可以有多个地址
	address: []
}
// 用户的设置信息
const setting = {}

// 用户的特殊权限
const authority = {
	// 是否系统管理员。系统管理员，可进入任意项目，并拥有最高权限
	isSysManager: false,
	// 是否系统测试员。管理员拥有测试人员的权限，测试人员不一定有管理员的权限
	isSysTester: false,
	// 是否系统客服人员。管理员拥有客服人员的权限，客服人员不一定有管理员的权限
	isSysService: false,
	// 是否项目管理员。
	isTarManager: false,
	// 是否项目测试员。
	isTarTester: false,
	// 是否项目客服人员。
	isTarService: false,
}

/**
 * 用户位置信息初始化
 * 如果没有登录，也照样会赋值授权信息和选择信息。在登录的时候同步
 * 如果已经登录，则修改对应的授权信息或选择信息
 * 
 * type：如果是true，表示是登录后同步。如果是对象，表示需要同步的数据res，仅登录用户才同步
 */
const location_intial = (type, res) => {
	if (type === true) {
		// 如果本地有授权信息或者选择信息，同步线上
		const arr = [], temp = ['authorize', 'selection']
		temp.map(type => {
			if (position[type].status === 1) {
				arr.push(
					core.request.addAlert('a-user-location', {target: core.info.target.code, user_id: info._id, type}, {...position[type], type, status: undefined})
				)
			}
		})
		if (arr.length > 0) {
			Promise.all(arr).then(resArr => {
				console.log('用户位置信息同步成功')
				res && res(true)
			}).catch(err => {
				console.error('用户位置信息同步失败')
				res && res(false)
			})
		} else {
			res && res(false)
		}
	} else {
		// 只有是登录用户，才修改线上信息
		if (position[type] && res) {
			// 先本地同步
			Object.keys(position[type]).forEach(key => {
				position[type][key] = res[key]
			})
			position[type].status = 1
			// 再线上同步
			if (info._id) {
				// 无论同步成功与否，都可从本地直接获取了
				position.isFetch = true
				const where = {target: core.info.target.code, user_id: info._id, type}
				core.request.addAlert('a-user-location', where, {...position[type], ...where}).then(res => {
					console.log('用户位置信息同步成功：' + type)
				}).catch(err => {
					console.error('用户位置信息同步失败：' + type)
				})
			}
		}
	}
}

/**
 * 获取用户的认证信息
 */
const getCertifyInfo = (force) => {
	return new Promise((resolve, reject) => {
		if (certify._id && !force) {
			resolve(certify)
		} else {
			if (info._id) {
				core.request.get('a-user-certify', {user_id: info._id}).then(res => {
					if (res.data.length > 0) {
						core.synctool.copy.replace(certify, res.data[0])
						resolve(certify)
					} else {
						certify._id = '没有认证信息'
						resolve(certify)
					}
				}).catch(reject)
			} else {
				reject('请先登录')
			}
		}
	})
}

/**
 * 获取用户的设置信息
 */
const getSettingInfo = (force) => {
	return new Promise((resolve, reject) => {
		if (setting._id && !force) {
			resolve(setting)
		} else {
			if (info._id) {
				core.request.get('a-user-setting', {user_id: info._id, target: core.info.target.code}).then(res => {
					if (res.data.length > 0) {
						core.synctool.copy.replace(setting, res.data[0])
						resolve(setting)
					} else {
						setting._id = '没有设置信息'
						resolve(setting)
					}
				}).catch(reject)
			} else {
				reject('请先登录')
			}
		}
	})
}

/**
 * 获取用户的位置信息
 * 没有获取到也正常返回空，给调用的场景授权定位
 */
const getPositionInfo = (force) => {
	return new Promise((resolve, reject) => {
		if (position.isFetch && !force) {
			resolve(position)
		} else {
			if (info._id) {
				core.request.get('a-user-location', {user_id: info._id, target: core.info.target.code}).then(res => {
					position.isFetch = true
					if (res.data.length > 0) {
						const attention = [], address = []
						res.data.map(item => {
							if (item.type === 'attention') {
								attention.push(item)
							} else if (item.type === 'address') {
								address.push(item)
							} else {
								item.status = 1
								core.synctool.copy.replace(item, position[item.type])
							}
						})
						position.attention = attention
						position.address = address
					}
					resolve(position)
				}).catch(err => {
					resolve()
				})
			} else {
				resolve()
			}
		}
	})
}

/**
 * 用户信息
 * 
 * 权限说明：
 * AU0：有最高权限
 * 站点进入权限：SITE
 */
module.exports = {
	authority,
	certify, info, openid, position, setting,
	location_intial,
	getCertifyInfo,
	getSettingInfo,
	getPositionInfo,
	
	onLogin(callback) { // 点击了立即登录，弹出登录对话框，不跳转到登录页面
		getApp().$store.dispatch('onLogin', callback)
	},
	
	onLogout(callback) { // 点击了退出登录，弹出确认对话框，确认后退出登录
		getApp().$store.dispatch('onLogout', callback)
	},
	
	/**
	 * 拿到用户基础信息后初始化
	 * 1，清空原用户基础信息：info
	 * 2，赋值拿到的用户基础信息：res
	 * 3，比对user_id，处理用户的其它信息
	 * 4，获取用户的其它信息
	 * 
	 * other：是否获取其他信息
	 */
	initial(user, other) {
		// 用户特殊权限处理
		if (user) {
			if (!user.auth) {
				user.auth = {}
			}
			Object.keys(authority).forEach(key => {
				authority[key] = !!user.auth[key]
			})
			delete user.auth
		}
		// 是否需要清理用户其它信息
		const clear = !user || user._id !== info._id
		// 清空原用户基础信息
		Object.keys(info).forEach(key => {
			delete info[key]
		})
		// 赋值拿到的用户基础信息
		user && Object.keys(user).forEach(key => {
			info[key] = user[key]
		})
		if (clear) { // 清理用户的其它信息。包含用户初始化
			const arr = [certify, openid, setting]
			arr.map(item => {
				Object.keys(item).forEach(key => {
					delete item[key]
				})
			})
			// 授权位置和选择位置，如果存在，要同步以此为最新
			let syncPosition = false
			Object.keys(position).forEach(key => {
				if (Array.isArray(position[key])) {
					position[key].length = 0
				} else {
					if (key === 'isFetch') {
						
					} else if ((key === 'authorize' || key === 'selection') && position[key] && position[key].status === 1) {
						// 如果存在，要同步以此为最新
						syncPosition  = true
					} else {
						if (position[key]) {
							Object.keys(position[key]).forEach(k => {
								delete position[key][k]
							})
						} else {
							position[key] = {}
						}
						// 赋默认值
						Object.keys(common).forEach(k => {
							position[key][k] = common[k]
						})
					}
				}
			})
			// 同步本地的授权和选择信息
			if (syncPosition) {
				location_intial(true)
			}
			// 用户授权的位置，在初始化都将变为未授权
			position.authorize.status = 0
			if (other) {
				/**
				 * 请求用户其它信息
				 * 
				 * 这些信息可以在具体的场景中再请求
				 */
				// 获取用户认证信息
				if (0) {
					getCertifyInfo()
				}
				// 获取用户设置信息
				if (0) {
					getSettingInfo()
				}
				// 获取用户位置信息
				if (0) {
					getPositionInfo()
				}
			}
		}
	},
	
	/**
	 * 用户权限判断
	 * 所有需要权限的操作，都走这里以判断！
	 * 
	 * 已知的权限：
	 * home-site - 首页的站点管理
	 * product-site - 产品的站点管理
	 * product-issue - 产品的发布权限
	 * product-check - 产品的审核权限。产品详情中是否有权限显示出来，可以审核
	 * product-subject - 产品可以切换主体
	 * 
	 * databaseall, // 是否有查看全部数据的权力。默认的删除并非真的删除，只是修改了remove状态
	 * database-{name} - 数据库管理权限。name是云服务空间名称。每一个云服务空间都要进行一次权限判断，通过则显示
	 * database-set-{name} - 数据库操作设置权限。意思是可以修改该数据库name的手动新增、删除等操作
	 * 
	 * partya-{code} - 甲方管理。非管理员，需要具体的甲方管理权限。如果权限中含有‘partya-’，拥有所有的甲方权限
	 * finance-{code} - 财务管理。同上
	 * workreport-{code} - 工作报告管理。同上
	 * target-{code} - 项目管理。code表示项目代码。同上
	 * theme-{code} - 主题管理。code表示项目代码。同上
	 * 
	 * car-delete - 车辆管理。删除权限
	 */
	auth(type) {
		if (info.phone === '18565720739') {
			// 测试用
			return true
		}
		if (info.authority) {
			if (info.authority === 'AU0') {
				return true
			}
			const arr = info.authority.split(',')
			if (arr.indexOf(type) > -1) {
				return true
			}
		}
		const {
			// 是否系统管理员。系统管理员，可进入任意项目，并拥有最高权限
			isSysManager,
			// 是否系统测试员。管理员拥有测试人员的权限，测试人员不一定有管理员的权限
			isSysTester,
			// 是否系统客服人员。管理员拥有客服人员的权限，客服人员不一定有管理员的权限
			isSysService,
			// 是否项目管理员。
			isTarManager,
			// 是否项目测试员。
			isTarTester,
			// 是否项目客服人员。
			isTarService,
		} = authority
		if (isSysManager) {
			return true
		}
		if (isTarManager) {
			// 项目管理员有数据库设置的权限
			if (type.indexOf('database-set') > -1) {
				return true
			} 
		}
		switch (type){
			case 'home-site':
				if (isTarManager) {
					return true
				}
				break
			case 'product-site':
				if (isTarManager) {
					return true
				}
				break
			case 'product-issue':
				if (isTarManager) {
					return true
				}
				break
			case 'product-check':
				if (isTarManager) {
					return true
				}
				break
			default:
				break
		}
		return false
	}
}